const HEX = (n, x = 16) => {
  return (v) => v.toString(x).padStart(n, 0)
}
const BITS = (...ar) => {
  let r = ar.reverse()
  return (v) => r.map(i => {
    let t = v & (0x0FFFF >> (16 - i));
    v >>= i;
    return t
  }).reverse()
}
const IN = (a, b) => {
  let r = (v) => (v >= a) && (v <= b)
  r.range = [a, b]
  return r
}
const NA = () => " - "

const 正常0 = {3: '异常', 0: '正常'}
const T02 = {
  0x00: "无接收错误",
  0x09: "奇偶校验错误",
  0x13: "停止位错误",
  0x1A: "字符间隔错误",
  0x25: "帧头错误",
  0x2C: "载荷标识错误",
  0x36: "命令类型错误",
  0x3F: "命令类型错误",
  0x5C: "校验和错误",
}
const T03 = {
  0b0000: "镜头温控未使能",
  0b0011: "主份传感器温升模式",
  0b0101: "主份传感器阈值模式",
  0b0110: "备份传感器温升模式",
  0b1001: "备份传感器阈值模式",
}
const 开3 = {0b00: "关", 0b11: "开",}
const 使能3 = {0b00: "未使能", 0b11: "使能",}
const 图像输出状态 = {0b0000: "未启动连续输出", 0b0011: "0.2Hz连续输出", 0b0101: "1Hz连续输出",}
const 图像模式 = {
  0b0000: "全图输出", 0b0011: "2:1像素合并输出", 0b0101: "4:1像素合并输出", 0b0110: "8:1像素合并输出",
  0b1001: "手动开窗模式", 0b1010: "自主开窗模式"
}
const 曝光模式 = {0b0000: "手动曝光模式", 0b0011: "自动曝光模式1", 0b0101: "自动曝光模式2", 0b0110: "自动曝光模式3",}
const 工作模式 = {0b0000: "初始化", 0b0011: "待机", 0b0101: "短曝光拍照模式", 0b0110: "长曝光拍照模式"}
//注一公式
const F01 = (v, a = -6.01188, b = 4622.53337, c = -86421.72414) => {
  let V_ref = 5, R_s = 162E3, R_p = 49.9E3, A = 3.0;
  let x1 =((4095 - v) * V_ref) / (4095 * A)
  let temp_In = (x1 * R_s * R_p) / (V_ref * R_p - x1 * (R_p + R_s));
  let temp = b ** 2 - 4 * c * (a - Math.log(temp_In));
  return (2 * c / (-b + Math.sqrt(temp))) - 273.15;
}
const F02 = () => {
}
//注三公式
const F03 = (v) => {
  let V_ref = 5, R_s = 10000, N = v,a = -6.01188,  b = 4622.53337, c = -86421.72414
  let x = ((255 - N) * V_ref) / 255
  let temp_In = (x * R_s) / (V_ref - x);
  let temp = b ** 2- 4 * c * (a - Math.log(temp_In));
  // return a- Math.log(temp_In)
  return (2 * c / (-b + Math.sqrt(temp))) - 273.15;
  }
const D01 = {0b00: '主', 0b11: '备'}
const Tm45_60 = IN(-45, 60)
        const TD01=(v)=>{
      // d: 时区为北京时的时候， 转换最终时间 需要减去offset 方可用 toISO 方法显示为北京时 - t.getTimezoneOffset()*60e3
      // 	  // d 指定时区为utc / toiso 也是utc 也就是与开始时间处于同一时区，处理过程就不需要在考虑时区问题了
       	        let d = new Date('2020-01-01T00:00:00Z')
       	        let t = parseInt(v.toString(16).padStart(12,0).slice(0,8),16)*1000 + (v & 0xFFFF)  + d.getTime()
       	        return new Date(t).toISOString().slice(0,23).replace('T',' ')
       	                        }
export function params() {
  return [
    //1,,包同步码,,16,,,固定为0xEB90,0xEB90,0xEB90,非0xEB90报警,非0xEB90报警
    new Params('a001', '包同步码', 16, null, null, NA, v => v === 0xEB90),
    // 2,,版本号,,3,,,固定为000b,000b,000b,非000b报警,非000b报警
    new Params('a002', '版本号', 3, null, null, NA, v => v === 0b000),
    // 3,,包标识-类型,,1,,,固定为0b,0b,0b,非0b报警,非0b报警
    new Params('a003', '包标识-类型', 1, null, null, NA, v => v === 0b0),
    // 4,,包标识-副导头标识,,1,,,固定为1b,1b,1b,非1b报警,非1b报警
    new Params('a004', '包标识-副导头标识', 1, null, null, null, v => v === 0b1),
    // 5,,包标识-应用过程标识符,,11,,,固定为00000010011b（工程参数源包）,00000010011b,00000010011b,非00000010011b报警,非00000010011b报警
    new Params('a005', '包标识-应用过程标识符', 11, null, null, null, v => v === 0b00000010011),
    // 6,,包序控制-分组标志,,2,,,固定为11b，即独立包,11b,11b,非11b报警,非11b报警
    new Params('a006', '包序控制-分组标志', 2, null, null, null, v => v === 0b11),
    // 7,,包序控制-包序列计数,,14,,,包计数，从0开始计数。,无,无,无,无
    new Params('a007', '包序控制-包序列计数', 14, null, null, null, null),
    // 8,,包数据域长度,,16,,,0x0047,0x0047,0x0047,非0x0047报警,非0x0047报警
    new Params('a008', '包数据域长度', 16, null, null, null, v => v === 0x0047),
    // 9,T,副导头（时间码）,,48,,源码,,无,无,无,无
    new Params('a009', '副导头（时间码）', 48, null, v=>TD01(v), null),
    // 10,,命令类型,,8,,,0x25,0x25,0x25,非0x25报警,非0x25报警
    new Params('a010', '命令类型', 8, null, null, HEX(2), v => v === 0x25),
    // 11,,工作模式,,4,,表格,按bit解析0000b-初始化0011b-待机0101b-短曝光拍照模式0110b-长曝光拍照模式,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a011', '工作模式', 4, null, null, v => 工作模式[v] || `Err-${v}`, v => !!工作模式[v]),
    // 12,,曝光模式,,4,,表格,按bit解析0000b-手动曝光模式0011b-自动曝光模式10101b-自动曝光模式20110b-自动曝光模式3,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a012', '曝光模式', 4, null, null, v => 曝光模式[v], v => !!曝光模式[v]),
    // 13,,图像模式,,4,,表格,按bit解析0000b-全图输出0011b-2:1像素合并输出0101b-4:1像素合并输出0110b-8:1像素合并输出1001b-手动开窗模式1010b-自主开窗模式,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a013', '图像模式', 4, null, null, v => 图像模式[v], v => !!图像模式[v]),
    // 14,,图像输出状态,,4,,表格,按bit解析0000b-未启动连续输出0011b-0.2Hz连续输出0101b-1Hz连续输出,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a014', '图像输出状态', 4, null, null, v => 图像输出状态[v], v => !!图像输出状态[v]),
    // 15,,曝光时间,μs,20,,表格,十进制解析,800000,380,大于800000报警,小于380报警
    new Params('a015', '曝光时间', 20, 'μs', null, null, v => v >= 380 && v <= 800000),
    // 16,,图像平均灰度计算值,无,12,,表格,手动曝光模式、自动曝光模式1下为全图平均灰度；自动曝光模式2和模式3下为目标平均灰度，十进制解析,无,无,无,无
    new Params('a016', '图像平均灰度计算值', 12, null, null, null, null),
    // 17,,图像输出帧计数,帧,8,,表格,十进制解析,无,无,无,无
    new Params('a017', '图像输出帧计数', 8, '帧'),
    // 18,,CMOS工作状态,,8,,表格,按bit解析bit7～bit6：CMOS供电状态
    // bit5～bit4：CMOS配置/接收训练状态
    // bit3～bit2：CMOS时钟/数据状态
    // bit1～bit0：焦平面温度状态
    // 00b-正常，11b-异常,仅列举值有效,仅列举值有效,出现异常（11b）或非列举值报警,出现异常（11b）或非列举值报警
    new Params('a018', 'CMOS工作状态', 8, null, BITS(2, 2, 2, 2), v => `CMOS供电状态:${正常0[v[0]]} CMOS配置/接收训练状态:${正常0[v[1]]} CMOS时钟/数据状态:${正常0[v[2]]} 焦平面温度状态:${正常0[v[3]]}`, v => !(v[0] + v[1] + v[2] + v[3])),
    // 19,,CMOS电流监控状态,,8,,表格,按bit解析bit7～bit6：电流监控使能状态00b-未使能，11b-使能bit5～bit4：电源开关状态00b-CMOS电源关，11b-COMS电源开bit3～bit0：CMOS下电计数，0～15计数,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a019', 'CMOS电流监控状态', 8, null, BITS(2, 2, 4), v => `电流监控:${使能3[v[0]]} 电源开关:${开3[v[1]]} 下电计数:${v[2]}`, v => !(!使能3[v[0]] || !开3[v[1]])),
    // 20,,镜头温控模式及状态,,8,,表格,
    // 按bit解析bit7～bit4：镜头温控模式0000b-镜头温控未使能0011b-主份传感器温升模式0101b-主份传感器阈值模式0110b-备份传感器温升模式1001b-备份传感器阈值模式
    // bit3～bit2：镜头前端加热器开关状态00b-关，11b-开
    // bit1～bit0：镜头后端加热器开关状态00b-关，11b-开,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a020', '镜头温控模式及状态', 8, null, BITS(4, 2, 2), v => `${T03[v[0]]} 前端加热器:${开3[v[1]]} 后端加热器:${开3[v[2]]}`, v => !(!T03[v[0]] || !开3[v[1]] || !开3[v[2]])),
    // 21,,镜头前端温度采集值,℃,12,amac1,表格、曲线,按公式解析，注1,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a021', '镜头前端温度采集值', 12, '℃', v => F01(v), v => v.toFixed(2), Tm45_60),
    // 22,,镜头后端温度采集值,℃,12,amac1,表格、曲线,按公式解析，注1,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a022', '镜头后端温度采集值', 12, '℃', v => F01(v), v => v.toFixed(2), Tm45_60),
    // 23,,安装面温度采集值,℃,12,amac1,表格、曲线,按公式解析，注1,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a023', '安装面温度采集值', 12, '℃', v => F01(v), v => v.toFixed(2), Tm45_60),
    // 24,,焦平面温度采集值,℃,12,amac1,表格、曲线,按公式解析，注1,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a024', '焦平面温度采集值', 12, '℃', v => F01(v), v => v.toFixed(2), Tm45_60),
    // 25,,RS-422接收正确计数,,8,,表格,十进制解析,无,无,无,无
    new Params('a025', 'RS-422接收正确计数', 8, null, null, null),
    // 26,,RS-422接收错误计数,,8,,表格,十进制解析,无,无,无,无
    new Params('a026', 'RS-422接收错误计数', 8, null, null, null),
    // 27,,RS-422接收错误类型,,8,,表格,最近一次接收错误类型十六进制解析0x00-无接收错误0x09-奇偶校验错误0x13-停止位错误0x1A-字符间隔错误0x25-帧头错误0x2C-载荷标识错误0x36-命令类型错误0x3F-有效数据错误0x5C-校验和错误,仅列举值有效,仅列举值有效,出现错误（非0x00）或非列举值报警,出现错误（非0x00）或非列举值报警
    new Params('a027', 'RS-422接收错误类型', 8, null, null, v => T02[v], v => !!T02[v]),
    // 28,,目标中心行号,,16,,表格,提取目标中心的行号，仅为偶数，十进制解析,3838,0,大于3838报警,无
    new Params('a028', '目标中心行号', 16, null, null, null, v => v <= 3838),
    // 29,,目标中心列号,,16,,表格,提取目标中心的列号，仅为偶数，十进制解析,5118,0,大于5118报警,无
    new Params('a029', '目标中心列号', 16, null, null, null, v => v <= 5118),
    // 30,,目标像素数,,16,,表格,目标在图像中占据的像素数，算法提取的目标区域行数或列数（取较大值），最大5120，十进制解析,5120,0,大于5120报警,无
    new Params('a030', '目标像素数', 16, null, null, null, v => v <= 5120),
    // 31,,度信息接收状态,,2,,表格,按bit解析00b-正常11b-异常,仅列举值有效,仅列举值有效,出现异常（11b）或非列举值报警,出现异常（11b）或非列举值报警
    new Params('a031', '温度信息接收状态', 2, null, null, v => 正常0[v], v => !v,),
    // 32,,平台信息接收状态,,2,,表格,按bit解析00b-正常11b-异常,仅列举值有效,仅列举值有效,出现异常（11b）或非列举值报警,出现异常（11b）或非列举值报警
    new Params('a032', '平台信息接收状态', 2, null, null, v => 正常0[v], v => !v,),
    // 33,,自动曝光平均灰度期望值,,12,,表格,自动曝光计算迭代的目标平均灰度值，十进制解析,无,无,无,无
    new Params('a033', '自动曝光平均灰度期望值', 12, null, null, null, null),
    // 34,,背景阈值参数,,12,,表格,用于自动曝光模式2和模式3的暗背景去除，十进制解析,无,无,无,无
    new Params('a034', '背景阈值参数', 12, null, null, null, null),
    // 35,,自动曝光时间约束值,μs,20,,表格,十进制解析,800000,380,大于800000报警,小于380报警
    new Params('a035', '自动曝光时间约束值', 20, 'μs', null, null,v => v >= 380 && v <= 800000),
    // 36,,开窗起始行号,,16,,表格,从0开始，只能为偶数行，十进制解析,3600,0,大于3600或奇数值报警,奇数值报警
    new Params('a036', '开窗起始行号', 16, null, null, null, v => v <= 3600 && !(v % 2)),
    // 37,,开窗起始列号,,16,,表格,从0开始，只能为偶数列，十进制解析,4880,0,大于4880或奇数值报警,奇数值报警
    new Params('a037', '开窗起始列号', 16, null, null, null, v => v <= 4880 && !(v % 2)),
    // 38,,窗口行数,,16,,表格,只取偶数，缺省为640，十进制解析,1920,240,大于1920或奇数值报警,小于240或奇数值报警
    new Params('a038', '窗口行数', 16, null, null, null, v => (v >= 240) && (v <= 1920) && !(v % 2)),
    // 39,,窗口列数,,16,,表格,只取偶数，缺省为640，十进制解析,1920,240,大于1920或奇数值报警,小于240或奇数值报警
    new Params('a039', '窗口列数', 16, null, null, null, v => (v >= 240) && (v <= 1920) && !(v % 2)),
    // 40,,焦平面温度监控使能状态,,4,,表格,按bit解析0000b-温度监控未使能0011b-温度监控使能,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    // const T05 = {0b00: "未使能", 0b11: "使能",}
    new Params('a040', '焦平面温度监控使能状态', 4, null, null, v => 使能3[v], v => !!使能3[v]),
    // 41,,CMOS3.3V电流监控参数,A,12,,表格,CMOS3.3V工作电流监控阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a041', 'CMOS3.3V电流监控参数', 12, 'A', null, null, null),
    // 42,,CMOS3.0V电流监控参数,A,12,,表格,CMOS3.0V工作电流监控阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a042', 'CMOS3.0V电流监控参数', 12, 'A', null, null, null),
    // 43,,CMOS2.1V电流监控参数,A,12,,表格,CMOS2.1V工作电流监控阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a043', 'CMOS2.1V电流监控参数', 12, 'A', null, null, null),
    // 44,,保留,,4,,表格,固定为0000b，十六进制解析,无,无,无,无
    new Params('a044', '保留', 4, null, null, null),
    // 45,,CMOS3.3V电流监控值,A,12,"amac2,3.3",表格、曲线,CMOS3.3V工作电流AD采集值，按公式解析，注2,无,无,解析后的电流值大于400mA时报警,无
    new Params('a045', 'CMOS3.3V电流监控值', 12, 'A', v => (3.3 * v - 4641.2)/1000, v => v.toFixed(3), v => v <= 0.4),
    // 46,,CMOS3.0V电流监控值,A,12,"amac2,3.0",表格、曲线,CMOS3.0V工作电流AD采集值，按公式解析，注2,无,无,解析后的电流值大于600mA时报警,无
    new Params('a046', 'CMOS3.0V电流监控值', 12, 'A', v => (3.6 * v - 5072.2)/1000, v => v.toFixed(3), v => v <= 0.6),
    // 47,,CMOS2.1V电流监控值,A,12,"amac2,2.1",表格、曲线,CMOS2.1V工作电流AD采集值，按公式解析，注2,无,无,解析后的电流值大于500mA时报警,无
    new Params('a047', 'CMOS2.1V电流监控值', 12, 'A', v => (4.0 * v - 5629.1)/1000, v => v.toFixed(3), v => v <= 0.5),
    // 48,,镜头前端备份温度,℃,8,amac3,表格、曲线,镜头前端备份温度值，来自RS422接收温度信息，按公式解析，注3,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a048', '镜头前端备份温度', 8, '℃', F03, v => v.toFixed(2), Tm45_60),
    // 49,,镜头后端备份温度,℃,8,amac3,表格、曲线,镜头后端备份温度值，来自RS422接收温度信息，按公式解析，注3,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a049', '镜头后端备份温度', 8, '℃', F03, v => v.toFixed(2), Tm45_60),
    // 50,,安装面备份温度,℃,8,amac3,表格、曲线,镜头安装面备份温度值，来自RS422接收温度信息，按公式解析，注3,解析后温度值70℃,解析后温度值-50℃,解析后温度值60℃,解析后温度值-45℃
    new Params('a050', '安装面备份温度', 8, '℃', F03, v => v.toFixed(2), Tm45_60),
    // 51,,镜头温控主传感器上限阈值参数,AD值,12,,表格,主传感器上限阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a051', '镜头温控主传感器上限阈值参数', 12, 'AD值', null, null, null),
    // 52,,镜头温控主传感器下限阈值参数,AD值,12,,表格,主传感器下限阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a052', '镜头温控主传感器下限阈值参数', 12, 'AD值', null, null, null),
    // 53,,镜头温控备传感器上限阈值参数,AD值,12,,表格,备传感器上限阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a053', '镜头温控备传感器上限阈值参数', 12, 'AD值', null, null, null),
    // 54,,镜头温控备传感器下限阈值参数,AD值,12,,表格,备传感器下限阈值参数，对应AD采集值，十进制解析,无,无,无,无
    new Params('a054', '镜头温控备传感器下限阈值参数', 12, 'AD值', null, null,null),
    // 55,,温控继电器主备选择状态,,4,,表格,按bit解析bit3～bit2：镜头前端继电器主备选择00b-主，11b-备bit1～bit0：镜头后端继电器主备选择00b-主，11b-备,仅列举值有效,仅列举值有效,非列举值报警,非列举值报警
    new Params('a055', '温控继电器主备选择状态', 4, null, BITS(2, 2), v => `镜头前端继电器:${D01[v[0]]} 镜头后端继电器:${D01[v[1]]}`, v => !(!D01[v[0]] || !D01[v[1]])),
    // 56,,CMOS数据接收训练计数,,4,,表格,十进制解析,无,无,无,无
    new Params('a056', 'CMOS数据接收训练计数', 4, null, null, null, null),
    // 57,,CMOS寄存器地址,,8,,表格,十进制解析,127,0,大于127报警,无
    new Params('a057', 'CMOS寄存器地址', 8, null, null, null, v => v <= 127),
    // 58,,查询OS寄存器读出值,,8,,表格,十六进制解析,无,无,无,无
    new Params('a058', '查询OS寄存器读出值', 8, null, null, null, null),
    // 59,,备用,,24,,表格,十六进制解析,无,无,无,无
    new Params('a059', '备用', 24, null, null, NA, null),
    // 60,,工程参数源包校验和,,8,,表格,十六进制解析从副导头开始到数据域的字节累加和,无,无,校验错误报警,校验错误报警
    new Params('a060', '工程参数源宝校验和', 8, null, null,null, null)
  ]
}

